package algorithm.encode.huffman;

import java.util.Map;

public class HuffmanCoding {
    HuffmanDictionary huffmanDictionary = null;

    public String encode(String input) {
        huffmanDictionary = new HuffmanDictionary(input);
        huffmanDictionary.build();
        String output = encodeInput(input, huffmanDictionary.getDictionary());
        return output;
    }

    public String decode(String input) {
        String output = decodeInput(input, huffmanDictionary.getCodeDictionary());
        return output;
    }

    private String decodeInput(String input, Map<String, String> codeDictionary) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < input.length(); ) {
            for (int j = i + 1; j <= input.length(); j++) {
                String code = input.substring(i, j);
                String data = codeDictionary.get(code);
                if (data != null) {
                    stringBuilder.append(data);
                    i = j;
                    break;
                } else if (j == input.length()) {
                    throw new RuntimeException(String.format("invalid input[%d:%d]: %s", i, j, code));
                } else {
                    continue;
                }
            }
        }
        return stringBuilder.toString();
    }

    private String encodeInput(String input, Map<String, String> dictionary) {
        StringBuffer stringBuffer = new StringBuffer();
        String[] inputChars = input.split("");
        for (int i = 0; i < inputChars.length; i++) {
            stringBuffer.append(dictionary.get(inputChars[i]));
        }
        return stringBuffer.toString();
    }
}
